# -- coding: utf-8 --
import inspect
import os

from wnboss04.util import FileParser


class Runner:

    # 1.找到test包下所有以test结尾的模块名，获得符合要求的多个模块名的列表
    def get_modules(self):
        all = os.listdir('../test')
        li = []
        for item in all:
            filename = item.split('.')[0]
            if filename.endswith('test'):
                li.append(filename)
        return li

    # __import__('模块的全路径', fromlist=['模块名'])  from wnboss03.test.ai_test
    def get_module_obj(self, module_name):
        import sys
        abs_path = sys.path[0]  # 绝对路径
        app_path = sys.path[1]  # 应用程序路径
        app_name = abs_path.replace(app_path, "").split('\\')[1]
        module_full_name = f'{app_name}.test.{module_name}'
        return __import__(module_full_name, fromlist=[module_name])

    # 2.遍历1的列表，找到模块名下的所有以Test结尾的类名，返回符合要求的多个测试类列表
    def get_classname(self, module):
        module_obj = self.get_module_obj(module)   # 根据模块名获取模块对象
        class_names = inspect.getmembers(module_obj, inspect.isclass)   # 返回的列表中的元素是元组
        class_name_list = []
        for cname in class_names:
            if cname[0].endswith('Test'):   # cname是元组，其第一项表示类的名称
                class_name_list.append(cname[0])
        return class_name_list

    def excute(self, module_name, class_name):
        # 将类名转化为类对象
        module_obj = self.get_module_obj(module_name)
        if hasattr(module_obj, class_name):
            class_obj = getattr(module_obj, class_name)()   # 获取类对象
        else:
            class_obj = None  # 没有获取到
        all = dir(class_obj)
        method_list = []
        for item in all:
            if item.startswith('test'):
                method_list.append(item)
        for method in method_list:
            getattr(class_obj, 'setup')()
            getattr(class_obj, method)()
            getattr(class_obj, 'teardown')()

    # 执行test包下的所有的测试模块下的所有的测试类下的所有的测试方法
    def run_all(self):
        # 3.遍历2的列表，找到类下所有以test开头的方法名，先执行setup方法，再执行test方法，然后执行teardown，完成所有方法的执行。
        module_names = self.get_modules()
        for module in module_names:
            class_names = self.get_classname(module)
            for class_name in class_names:
                self.excute(module, class_name)

    # 执行指定的测试方法
    def run_suite(self):
        test_method_list = FileParser.read_txt('suite', '#')   # 这里的元素应该是：测试模块名+测试类名+测试方法名
        for item in test_method_list:
            module_name = item.split('.')[0]
            class_name = item.split('.')[1]
            method_name = item.split('.')[2]
            module_obj = self.get_module_obj(module_name)
            class_obj = getattr(module_obj, class_name)()
            getattr(class_obj, 'setup')()
            getattr(class_obj, method_name)()
            getattr(class_obj, 'teardown')()


if __name__ == '__main__':

    runner = Runner()
    # runner.run_all()
    # print(runner.get_modules())
    # print(runner.get_module_obj('ai_test'))
    # runner.get_classname()
    runner.run_suite()
